/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2021-03-10 16:50:45
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-04-06 14:01:43
 * @Description: file content
 */


import mitt from "mitt"


const handleData = (data) => {
  let ret;
  if (Array.isArray(data) || typeof data === "object") {
    try {
      ret = JSON.stringify(data);
    } catch (error) {
      ret = data.toString();
    }
  } else if (["string", "number", "boolean"].includes(typeof data)) {
    ret = data;
  } else {
    ret = data.toString ? data.toString() : data;
  }
  return ret;
}

const createWsuid = () => {
  const a = Math.random().toString(36).replace(".", "");
  const b = Math.random().toString(36).replace(".", "");
  return a + b;
}

export default class MyWebSocket extends WebSocket {
  /**
   * Creates an instance of MyWebSocket.
   * @param {*} host 连接的主机，host port和路径。不需要search查询参数。
   * @param {*} [args={}] 此处的参数将被做成search参数赋给host后面。
   * @param {*} protocols
   * @memberof MyWebSocket
   */
  constructor(host, args = {}, protocols) {
    if (!args.wsuid) {
      args.wsuid = createWsuid();
    }
    const argss = Object.keys(args).map(item => {
      return item + '=' + args[item]
    })
    host += argss.length > 0 ? "?" + argss.join("&") : "";
    super(host, protocols);
    this.wsuid = args.wsuid;
    this.emitter = mitt()
    this._init()
  }

  _init() {
    super.onmessage = (msg) => {
      // console.log(msg);
      const data = msg.data;
      // 如果是传文件
      if (data instanceof Blob) {
        this.emitter.emit('get-file', data);
        return;
      }
      let ret = null;
      try {
        ret = JSON.parse(data)
      } catch (error) {
        ret = data;
      }
      // console.log(ret);
      if (ret && ret.event) {
        this.emitter.emit(ret.event, ret)
      } else {
        this.emitter.emit("message", msg)
      }
    }

    super.onopen = (msg) => {
      this.emitter.emit('open', msg)
    }

    super.onerror = (err) => {
      this.emitter.emit('error', err)
    }

    super.onclose = (data) => {
      this.emitter.emit('close', data)
    }

  }

  /** 发送消息 类似看做触发事件。但会send给服务器再接收同名事件响应。若需本地发送事件，需instance.emitter.emit */
  emit(event, data) {
    super.send(
      handleData({
        event: event,
        wsuid: this.wsuid,
        data,
      })
    )
    // this.emitter.emit(event, data)
  }

  /**
   *ws发送文件
   *
   * @memberof MyWebSocket
   */
  sendFile(file) {

    const reader = new FileReader();
    reader.readAsArrayBuffer(file)
    reader.onload = (e) => {
      const binStr = e.target.result
      // console.log(binStr);
      super.send(binStr)
    }

  }

  /** 监听自定义事件 */
  on(event, callback) {
    this.emitter.on(event, callback)
  }

  /** 监听一次事件，只要执行一次，就取消监听 */
  once(event, callback) {
    const cb = (...args) => {
      callback(...args)
      this.emitter.off(event, cb)
    }
    this.emitter.on(event, cb)
  }

  /** 移除某事件上的某监听回调 */
  off(event, cb) {
    this.emitter.off(event, cb)
  }
}
